package ai.people.netmon.warning.service.impl;

import ai.people.core.common.util.ApplicationContextUtil;
import ai.people.core.security.support.RequestHolderUtil;
import ai.people.netmon.framework.domain.warning.entity.WarningInfoCollect;
import ai.people.netmon.framework.domain.warning.entity.WarningInfoMaterial;
import ai.people.netmon.framework.domain.warning.entity.WarningInfoMaterialDetail;
import ai.people.netmon.framework.domain.warning.request.material.MaterialSaveRequest;
import ai.people.netmon.warning.dict.DictGrpcClient;
import ai.people.netmon.warning.mapper.WarningInfoMaterialDetailMapper;
import ai.people.netmon.warning.mapper.WarningInfoMaterialMapper;
import ai.people.netmon.warning.service.WarningInfoMaterialService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
* @author ligua
* @description 针对表【warning_info_material(预警素材)】的数据库操作Service实现
* @createDate 2022-07-28 17:50:38
*/
@Service
@RequiredArgsConstructor
public class WarningInfoMaterialServiceImpl extends ServiceImpl<WarningInfoMaterialMapper, WarningInfoMaterial>
    implements WarningInfoMaterialService{

    private final WarningInfoMaterialMapper warningInfoMaterialMapper;

    private final WarningInfoMaterialDetailMapper warningInfoMaterialDetailMapper;

    @Resource
    private RedissonClient redissonClient;

    /**
     * 查询单个 根据uid和infoId和信息平台
     *
     * @param infoMaterial 素材
     * @return {@link WarningInfoMaterial}
     */
    private WarningInfoMaterial getOneByUidInfoIdAndPlatform(WarningInfoMaterial infoMaterial) {
        return warningInfoMaterialMapper.selectOne(new LambdaQueryWrapper<WarningInfoMaterial>()
                .eq(Objects.nonNull(infoMaterial.getMaterialUserId()), WarningInfoMaterial::getMaterialUserId, infoMaterial.getMaterialUserId())
                .eq(Objects.nonNull(infoMaterial.getMaterialInfoId()), WarningInfoMaterial::getMaterialInfoId, infoMaterial.getMaterialInfoId())
                .eq(Objects.nonNull(infoMaterial.getMaterialInfoPlatform()), WarningInfoMaterial::getMaterialInfoPlatform, infoMaterial.getMaterialInfoPlatform())
                .eq(WarningInfoMaterial::getIsDelete, 0));
    }

    /**
     * 添加素材
     *
     * @param infoMaterial 信息素材
     * @return {@link Integer}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addMaterial(WarningInfoMaterial infoMaterial, String rowDataJson) {
        RLock lock = redissonClient.getLock("material:info:save:" + infoMaterial.getMaterialUserId());
        try {
            if(lock.tryLock(6, TimeUnit.SECONDS)){
                WarningInfoMaterial one = getOneByUidInfoIdAndPlatform(infoMaterial);
                if(one == null){
                    int i = warningInfoMaterialMapper.insert(infoMaterial);
                    if(i > 0){
                        return warningInfoMaterialDetailMapper.insert(WarningInfoMaterialDetail.builder()
                                .materialId(infoMaterial.getId())
                                .isDelete(0)
                                .createTime(LocalDateTime.now())
                                .rowDataJson(rowDataJson)
                                .build());
                    }
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if(lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
        return 0;
    }

    /**
     * 删除素材
     *
     * @param infoMaterial 信息素材
     * @return {@link Integer}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer deleteMaterial(WarningInfoMaterial infoMaterial) {
        RLock lock = redissonClient.getLock("material:info:save:" + infoMaterial.getMaterialUserId());
        try {
            if(lock.tryLock(6, TimeUnit.SECONDS)){
                WarningInfoMaterial one = getOneByUidInfoIdAndPlatform(infoMaterial);
                if(one != null){
                    int i = warningInfoMaterialMapper.updateById(WarningInfoMaterial.builder().id(one.getId()).isDelete(1).build());
                    if(i > 0){
                        return warningInfoMaterialDetailMapper.deleteByMaterialId(one.getId());
                    }
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if(lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
        return 0;
    }

    /**
     * 通过参数集合批量查询素材库记录
     *
     * @param checkParamList 检查参数集合
     * @return {@link List}<{@link WarningInfoCollect}>
     */
    @Override
    public List<WarningInfoMaterial> batchQueryByParamList(List<WarningInfoMaterial> checkParamList) {
        List<WarningInfoMaterial> result = Lists.newArrayList();
        if(CollectionUtils.isEmpty(checkParamList)){
            return Lists.newArrayList();
        }
        List<List<WarningInfoMaterial>> partition = Lists.partition(checkParamList, 200);
        partition.forEach(list-> result.addAll(warningInfoMaterialMapper.selectByParamList(list)));
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer batchSave(Integer materialSource, List<MaterialSaveRequest> list) {
        if(CollectionUtils.isEmpty(list)){
            return 0;
        }

        DictGrpcClient dictService = ApplicationContextUtil.getBean(DictGrpcClient.class);
        Map<String, String> platformNameMap = dictService.getDictMap("warning_message_source");
        HashMap<String, String> newPlatformNameMap = Maps.newHashMap();
        platformNameMap.keySet().forEach(o-> newPlatformNameMap.put(platformNameMap.get(o), o));
        list.forEach(o->o.setPlatform(newPlatformNameMap.getOrDefault(o.getPlatform(),o.getPlatform())));

        //参数去重
        list = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                new TreeSet<>(Comparator.comparing(o -> o.getMessageContent().getPlatform() + "-" + o.getMessageContent().getId()))), ArrayList::new));

        HashMap<String, String> map = Maps.newHashMap();
        List<WarningInfoMaterial> materialList = Lists.newArrayList();
        for (MaterialSaveRequest materialSaveRequest : list) {
            materialList.add(WarningInfoMaterial.builder()
                    .materialUserId(RequestHolderUtil.getUserId())
                    .materialInfoPlatform(materialSaveRequest.getMessageContent().getPlatform())
                    .materialInfoId(materialSaveRequest.getMessageContent().getId())
                    .materialSource(materialSource)
                    .materialInfoAccountTitle(materialSaveRequest.getMessageContent().getTitle())
                    .materialInfoContent(materialSaveRequest.getMessageContent().getContent())
                    .materialInfoEmotion(materialSaveRequest.getMessageContent().getEmotion())
                    .materialInfoLabel(materialSaveRequest.getMessageContent().getLabel())
                    .materialInfoReleaseTime(materialSaveRequest.getMessageContent().getTime())
                    .createTime(LocalDateTime.now())
                    .isDelete(0)
                    .build());
            map.put(materialSaveRequest.getMessageContent().getPlatform() + "-" + materialSaveRequest.getMessageContent().getId(), JSON.toJSONString(materialSaveRequest.getMessageContent()));
        }

        //去重
        List<WarningInfoMaterial> warningInfoMaterials = batchQueryByParamList(materialList);
        if(!CollectionUtils.isEmpty(warningInfoMaterials)){
            List<String> collect = warningInfoMaterials.stream().map(o -> o.getMaterialInfoPlatform() + "-" + o.getMaterialInfoId()).collect(Collectors.toList());
            materialList = materialList.stream().filter(o->!collect.contains(o.getMaterialInfoPlatform() + "-" + o.getMaterialInfoId())).collect(Collectors.toList());
        }

        if(!CollectionUtils.isEmpty(materialList)){
            Integer i = warningInfoMaterialMapper.batchInsert(materialList);
            if(i > 0){
                warningInfoMaterials = batchQueryByParamList(materialList);
                List<WarningInfoMaterialDetail> materialDetailList = Lists.newArrayList();
                warningInfoMaterials.forEach(o->{
                    materialDetailList.add(WarningInfoMaterialDetail.builder()
                            .materialId(o.getId())
                            .rowDataJson(map.get(o.getMaterialInfoPlatform()+ "-" + o.getMaterialInfoId()))
                            .createTime(LocalDateTime.now())
                            .isDelete(0)
                            .build());
                });
                return warningInfoMaterialDetailMapper.batchInsert(materialDetailList);
            }
        }
        return 0;
    }
}




